package com.simple.util.common;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class StringUtil {
	public static String subStrByCodePoints(final String inputString, final int len) {
        String s = inputString;
        if (s.codePointCount(0, s.length()) > len) {
            s = s.substring(0,s.offsetByCodePoints(0, len));
        }
        return s;
    }
    
    public static String subStrByCodePointsWithMore(final String inputString, final int len) {
        String s = inputString;
        if (s.codePointCount(0, s.length()) > len) {
            s = s.substring(0,s.offsetByCodePoints(0, len-1))+"...";
        }
        return s;
    }
    
    public static String subStringByCodePoints(final String inputString, final int start, final int end) {
        final String s1 = subStrByCodePoints(inputString,start);
        final String s2 = subStrByCodePoints(inputString,end);
        return s2.substring(s1.length(),s2.length());
    }
    
    /**
     * get only key for database
     * @param content
     * @return
     */
    public static String getOnlyKey(){
        return String.valueOf(UUID.randomUUID()).replace("-", "");
    }
    
    public static String  xssAndAddHyperLinkStr(final String input){
        final String str = XSSUtil.htmlEncode(input);
        
        final String webStartRegex = "([f|F][t|T][p|P]|[h|H][t|T][t|T][p|P]|[h|H][t|T][t|T][p|P][s|S])(&#58;&#47;&#47;)";
        //\w.-_/:?%&=
        final String httpRegex="(("+webStartRegex+")|((?!"+webStartRegex+")[w|W]{3}\\.))(\\w|\\.|\\-|_|(&#47;)|(&#58;)|(&#63;)|(&#37;)|(&#38;)|(&#61;))+";
        final Pattern httpPattern = Pattern.compile(httpRegex);
        final Matcher httpMatcher = httpPattern.matcher(str);  
        
        final StringBuffer sb = new StringBuffer();
        while (httpMatcher.find()) {
            final String matchStr = httpMatcher.group();
            if(matchStr.toLowerCase(Locale.getDefault()).indexOf("www")==0){
                httpMatcher.appendReplacement(sb, "<a href='http://"+matchStr+"' target='blank' >"+matchStr+"</a>");
            }else{
                httpMatcher.appendReplacement(sb, "<a href='"+matchStr+"' target='blank' >"+matchStr+"</a>");
            }
        }
        httpMatcher.appendTail(sb);
        
        return sb.toString();
    }
    
    /**
	 * Validate input value is empty.
	 * 
	 * @param value
	 *            input String to Validate
	 * @return If value is null, return true; otherwise, return false
	 */
	public static boolean isNull(final String value) {
		return (null == value || value.trim().equals(""));
	}

	/**
	 * Validate input value is Digit.
	 * 
	 * @param c
	 *            the c
	 * @return If value is Digit, return true; otherwise, return false
	 */
	public static boolean isDigit(final char c) {
		return c >= '0' && c <= '9';
	}

	/**
	 * Validate input value is Date.
	 * 
	 * @param date
	 *            Input String to Validate
	 * @param pattern
	 *            pattern
	 * @return If value is Date, return true; otherwise, return false
	 */
	public static boolean isDate(final String date, final String pattern) {
		boolean result = true;
		try {
			final SimpleDateFormat sdf = new SimpleDateFormat(pattern, Locale.ENGLISH);
			sdf.parse(date);
		} catch (Exception e) {
			result = false;
		}
		return result;
	}

	/**
	 * Replace the string content.
	 * 
	 * @param paramStrSource
	 *            String Source
	 * @param strFrom
	 *            the characters from replace
	 * @param strTo
	 *            the characters to replace
	 * @return Replaced string
	 */
	public static String replace(final String paramStrSource, final String strFrom,
	        final String strTo) {
		String strSource = paramStrSource;
		final StringBuffer strDest = new StringBuffer("");
		final int intFromLen = strFrom.length();
		int intPos;

		while ((intPos = strSource.indexOf(strFrom)) != -1) {
			strDest.append(strSource.substring(0, intPos));
			strDest.append(strTo);
			strSource = strSource.substring(intPos + intFromLen);
		}
		strDest.append(strSource);

		return strDest.toString();
	}

	/**
	 * Replace the string content.
	 * 
	 * @param value
	 *            String Source
	 * @param from
	 *            the from
	 * @param to
	 *            the characters to replace
	 * @param ignoreCase
	 *            ignore Case(Lower Case)
	 * @return Replaced string
	 */
	public static String replaceAll(final String value, final String from, final String to,
	        final boolean ignoreCase) {
		String result = null;
		if (null != value) {
			final String activeValue = ignoreCase ? value.toLowerCase(Locale.ENGLISH) : value;
			final String fromValue = ignoreCase ? from.toLowerCase(Locale.ENGLISH) : from;

			final List<Integer> occurences = findOccurences(activeValue, fromValue);

			final StringBuffer buf = new StringBuffer();
			buf.append(value);
			int offset = 0;
			for (final Iterator<Integer> it = occurences.iterator(); it.hasNext();) {
				final Integer i = (Integer) it.next();
				final int index = i.intValue() + offset;
				buf.replace(index, index + from.length(), to);
				offset += to.length() - from.length();
			}
			result = buf.toString();
		}
		return result;
	}
	
	/**
	 * According to the patterns Completed s is split.
	 * 
	 * @param s
	 *            line
	 * @param patterns
	 *            patterns
	 * @return split of list
	 */
	public static List<String> split(final String s, final String[] patterns) {
		final Set<String> checkedPatterns = new HashSet<String>();
		Arrays.sort(patterns);
		List<String> result = null;
		for (int i = patterns.length - 1; i >= 0; i--) {
			if (i == patterns.length - 1) {
				result = split(s, patterns[i], true);
			} else {
				int count = 0;
				while (true) {
					if (count == result.size()) {
						break;
					}
					final String temp = (String) result.get(count);
					if (checkedPatterns.contains(temp)) {
						count++;
					} else {
						final List<String> newResult = split(temp, patterns[i], true);
						if (newResult.size() == 1) {
							count++;
						} else {
							result.remove(count);
							result.addAll(count, newResult);
							count += newResult.size();
						}
					}
				}
			}
			checkedPatterns.add(patterns[i]);
		}
		return result;
	}

	/**
	 * According to the regex position in str,Completed str is split.
	 * 
	 * @param target
	 *            the target
	 * @param regex
	 *            regex
	 * @return split of list
	 */
	public static List<String> splitByTrim(final String target, final String regex) {
		final List<String> list = new ArrayList<String>();
		boolean start = true;

		String s = "";
		if (null != target) {
			s = target;
		}

		while (start) {
			s = s.trim();
			if (s.indexOf(regex) != -1) {
				final int beginIndex = s.indexOf(regex);
				list.add(s.substring(0, beginIndex));

				s = s.substring(beginIndex + 1).trim();
			} else {
				start = false;
				list.add(s);
			}
		}

		return list;
	}

	/**
	 * Split.
	 * 
	 * @param s
	 *            the s
	 * @param pattern
	 *            the pattern
	 * @return the list
	 */
	public static List<String> split(final String s, final String pattern) {
		return split(s, pattern, false);
	}

	/**
	 * According to the patterns Completed s is split.
	 * 
	 * @param s
	 *            line
	 * @param pattern
	 *            the pattern
	 * @param includePattern
	 *            includePattern
	 * @return split of list
	 */
	public static List<String> split(final String s, final String pattern,
	        final boolean includePattern) {
		final List<String> result = new LinkedList<String>();
		int pos = 0;
		while (true) {
			if (pos == s.length()) {
				break;
			}

			final int index = s.indexOf(pattern, pos);
			if (index == -1) {
				result.add(s.substring(pos, s.length()));
				break;
			} else {
				result.add(s.substring(pos, index));
				if (includePattern) {
					result.add(s.substring(index, index + pattern.length()));
				}
				pos = index + pattern.length();
			}
		}
		return result;
	}
	
	/**
	 * substring string as length.
	 * 
	 * @param inputString
	 *            the input string
	 * @param len
	 *            the len
	 * @return the string
	 */
	public static String subStr(final String inputString, final int len) {
		String s = inputString;
		if (s.length() > len) {
			s = s.substring(0, len);
		}
		return s;
	}
	
	/**
	 * Check is decimal.
	 * 
	 * @param number
	 *            the number
	 * @return true, if successful
	 */
	public static boolean checkIsDecimal(final String number) {
		boolean result = true;
		String number1 = "";
		if ((null == number) || ("".equals(number.trim()))) {
			result = false;
		} else {
			final int indexFu = number.indexOf('.');
			if (indexFu > 0) {
				result = false;
			} else if (indexFu == 0) {
				number1 = number.substring(1);
				final int index = number1.indexOf('.');
				if (index < 0) {
					result = isNumeric(number1);
				} else {
					final String num1 = number1.substring(0, index);
					final String num2 = number1.substring(index + 1);
					result = isNumeric(num1) && isNumeric(num2);
				}
			}
		}
		return result;

	}

	/**
	 * Checks if is numeric.
	 * 
	 * @param str
	 *            the str
	 * @return true, if is numeric
	 */
	public static boolean isNumeric(final String str) {
		boolean result = true;
		if (null == str) {
			result = false;
		} else {
			final int sz = str.length();
			for (int i = 0; i < sz; i++) {
				if (!Character.isDigit(str.charAt(i))) {
					result = false;
				}
			}
		}
		return result;
	}

	/**
	 * Checks if is integer.
	 * 
	 * @param str
	 *            the str
	 * @return true, if is integer
	 */
	public static boolean isInteger(final String str) {
		boolean result = false;
		try {
			Integer.parseInt(str);
			result = true;
		} catch (Exception e) {
			result = false;
		}	
		return result;
	}
	
	
	/**
	 * If the target length for less than maxLength length,On the right complement pad.
	 * 
	 * @param target
	 *            target
	 * @param pad
	 *            pad
	 * @param maxLength
	 *            maxLength
	 * @return To meet the requirements of a string
	 */
	public static String rightPad(final String target, final String pad, final int maxLength) {
		final StringBuffer targetValue = new StringBuffer();
		targetValue.append(null == target ? "" : target);

		while (true) {
			if (targetValue.length() < maxLength) {
				targetValue.append(pad);
			} else {
				break;
			}
		}
		return targetValue.toString();
	}

	/**
	 * If the target length for less than maxLength length,On the left complement pad.
	 * 
	 * @param target
	 *            target
	 * @param pad
	 *            pad
	 * @param maxLength
	 *            maxLength
	 * @return To meet the requirements of a string
	 */
	public static String leftPad(final String target, final String pad, final int maxLength) {
		final StringBuffer targetValue = new StringBuffer();
		targetValue.append(null == target ? "" : target);

		while (true) {
			if (targetValue.length() < maxLength) {
				final String s = pad + targetValue.toString();
				targetValue.setLength(0);
				targetValue.append(s);
			} else {
				break;
			}
		}
		return targetValue.toString();
	}
	
	/**
	 * find an string in the string of position.
	 * 
	 * @param content
	 *            String Source
	 * @param matchValue
	 *            the characters from find
	 * @return find results
	 */
	private static List<Integer> findOccurences(final String content, final String matchValue) {
		final List<Integer> occurences = new LinkedList<Integer>();

		int pos = 0;
		while (pos < content.length()) {
			final int index = content.indexOf(matchValue, pos);
			if (index == -1) {
				break;
			}
			occurences.add(Integer.valueOf(String.valueOf(index)));
			pos = index + matchValue.length();
		}

		return occurences;
	}
}
